home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_12 / 1012063a < prev    next >
Text File  |  1992-10-11  |  16KB  |  726 lines

  1. /* 
  2.  * mpu.c 
  3.  * device driver for mpu-401 midi card
  4.  */
  5.  
  6. #include "../h/param.h"
  7. #include "../h/types.h"
  8. #include "../h/dir.h"
  9. #include "../h/signal.h"
  10. #include "../h/page.h"
  11. #include "../h/seg.h"
  12. #include "../h/user.h"
  13. #include "../h/file.h"
  14. #include "../h/tty.h"
  15. #include "../h/systm.h"
  16. #include "../h/conf.h"
  17. #include "../h/errno.h"
  18. #include "mpu.h"
  19.  
  20. /* external support prototypes */
  21.  
  22. int inb(int);
  23. void outb(int, int);
  24. caddr_t cvttoaddr(faddr_t);
  25. int fubyte(faddr_t);
  26. void subyte(char *, int);
  27. int copyin(faddr_t, char *, int);
  28.  
  29. void printcfg(char *, int, int, int, int, char *, ...);
  30. void printf(char *, ...);
  31. int getchar(void);
  32. void putchar(int);
  33.  
  34. int sleep(caddr_t, int);
  35. void wakeup(caddr_t);
  36. int timeout(int (*)(), caddr_t, int);
  37. void untimeout(int);
  38.  
  39. int spl6(void);
  40. void splx(int);
  41.  
  42. int cpass(void);
  43. int passc(int);
  44. int getc(struct clist *);
  45. int putc(int, struct clist *);
  46.  
  47. #define DRIVERID  0x00  /* driver version */
  48.  
  49. /* I/O addresses and vector */
  50. /* if using IRQ 2, set VECTOR to 25 (030+VECTOR-1) */
  51. #define VECTOR  25
  52. #define BASE    0x220     /* I/O address of mpu card */
  53. #define CMD     (BASE+1)  /* command output port */
  54. #define STATUS  (BASE+1)  /* mpu status port */
  55. #define DATA    BASE      /* data input port */
  56.  
  57. /* Status flags (neg logic) */
  58. #define RR_F    0x40      /* mpu ready to receive */
  59. #define DA_F    0x80      /* data available flag */
  60.  
  61. /* Test RR and DA flags */
  62. #define RR()    (!(INB(STATUS)&RR_F))
  63. #define rr()    (!(inb(STATUS)&RR_F))
  64. #define DA()    (!(INB(STATUS)&DA_F))
  65. #define da()    (!(inb(STATUS)&DA_F))
  66.  
  67. /* Device interrupt level */
  68. #define SPLINT  spl6
  69.  
  70. /* Busy-wait looping count */
  71. #define SPIN    100000
  72.  
  73. #define ACK     0xFE    /* mpu command acknowledge */
  74.  
  75. #define YES     1
  76. #define NO      0
  77.  
  78. #define E_OK      0     /* ok return code */
  79. #define E_TIMEOUT 1     /* timeout return code */
  80. #define E_INTR    2     /* interrupt return code */
  81.  
  82. #define PRI (PZERO+1)   /* sleep/wakeup priority */
  83.  
  84. static struct clist in_q;   /* input queue */
  85. static int busy = NO;       /* driver busy flag */
  86. static int exist = NO;      /* mpu card found flag */
  87. static int isopen = NO;     /* exclusive use flag */
  88. static int debug = 0;       /* debugging level */
  89. static int waitda = 0;      /* result DA timer */
  90.  
  91. /* local prototypes */
  92.  
  93. static int reset(void);
  94. static int waitRR(void);
  95. static int mpucmd(int);
  96. static int mpuinb(int);
  97. static void mpuoutb(int, int);
  98.  
  99. #define OUTB(addr,byte)   mpuoutb((addr),(byte))
  100. #define INB(addr)         mpuinb(addr)
  101.  
  102. /*-----------------------------------------------------
  103.  * mpuinit - determine if device exists at BASE address
  104.  */
  105.  
  106. void mpuinit()
  107. {
  108.   int i, ver = 0, rev = 0;
  109.  
  110.   in_q.c_cc = 0;  /* input q is empty */
  111.  
  112.   /*
  113.    * see if it's there by trying to reset
  114.    */
  115.   outb(CMD, MPU_RESET);
  116.   for (i = 0; i < SPIN; ++i)
  117.     if (da())
  118.       break;
  119.   if (i == SPIN) {
  120.     outb(CMD, MPU_RESET);
  121.     for (i = 0; i < SPIN; ++i)
  122.       if (da())
  123.         break;
  124.     if (i == SPIN)
  125.       goto NOTFOUND;
  126.   }
  127.   if (inb(DATA) != ACK)
  128.     goto NOTFOUND;
  129.  
  130.   /*
  131.    * get firmware version
  132.    */
  133.   for (i = 0; i < SPIN; ++i)  /* wait for RR */
  134.     if (rr())
  135.       break;
  136.   if (i == SPIN)              /* timed out */
  137.     goto NOTFOUND;
  138.   outb(CMD, MPU_VERSION);     /* send request */
  139.   for (i = 0; i < SPIN; ++i)  /* wait for ack */
  140.     if (da() && inb(DATA) == ACK)
  141.       break;
  142.   if (i == SPIN)              /* timed out */
  143.     goto NOTFOUND;
  144.   for (i = 0; i < SPIN; ++i)  /* wait for data */
  145.     if (da()) {
  146.       ver = inb(DATA);        /* read version */
  147.       break;
  148.     }
  149.   if (i == SPIN)              /* timed out */
  150.     goto NOTFOUND;
  151.  
  152.   /*
  153.    * get firmware revision
  154.    */
  155.   for (i = 0; i < SPIN; ++i)  /* wait for RR */
  156.     if (rr())
  157.       break;
  158.   if (i == SPIN)              /* timed out */
  159.     goto NOTFOUND;
  160.   outb(CMD, MPU_REVISION);    /* send request */
  161.   for (i = 0; i < SPIN; ++i)  /* wait for ACK */
  162.     if (da() && inb(DATA) == ACK)
  163.       break;
  164.   if (i == SPIN)              /* timed out */
  165.     goto NOTFOUND;
  166.   for (i = 0; i < SPIN; ++i)  /* wait for data */
  167.     if (da()) {
  168.       rev = inb(DATA);        /* read revision */
  169.       break;
  170.     }
  171.  
  172.   printcfg("mpu", BASE, 1, VECTOR, -1,
  173.    "ver=%d rev=%d did=%d", ver, rev, DRIVERID);
  174.   exist = YES;
  175.   return;
  176.  
  177. NOTFOUND:
  178.   printf("MPU not found at %x\n", BASE);
  179. }
  180.  
  181. /*-----------------------------------------------------
  182.  * mpuopen - check device availability and
  183.  *           ensure exclusive access
  184.  */
  185.  
  186. void mpuopen(dev, flag, id)
  187. int dev, flag, id;
  188. {
  189.   if (debug)
  190.     printf("open: dev=%x flag=%x id=%x\n", dev, flag,
  191.             id);
  192.  
  193.   if (!exist) {
  194.     u.u_error = ENXIO;
  195.     if (debug)
  196.       printf("open: device doesn't exist\n");
  197.     return;
  198.   }
  199.   if (isopen) {
  200.     u.u_error = EBUSY;
  201.     if (debug)
  202.       printf("open: failed EBUSY\n");
  203.     return;
  204.   }
  205.   isopen = YES;
  206.   if (reset() != E_OK) {
  207.     u.u_error = EIO;
  208.     if (debug)
  209.       printf("open: failed can't reset mpu\n");
  210.     isopen = NO;
  211.   }
  212. }
  213.  
  214. /*-----------------------------------------------------
  215.  * mpuclose - reset mpu and give up exclusive access
  216.  */
  217.  
  218. void mpuclose(dev, flag)
  219. int dev, flag;
  220. {
  221.   if (debug)
  222.     printf("close: dev=%x flag=%x\n", dev, flag);
  223.  
  224.   (void) reset();
  225.   while (getc(&in_q) != -1)   /* eat in_q */
  226.     ;
  227.   busy = isopen = NO;
  228. }
  229.  
  230. /*-----------------------------------------------------
  231.  * mpuread - read data from mpu
  232.  */
  233.  
  234. void mpuread(dev)
  235. int dev;
  236. {
  237.   int byte, oldpri;
  238.  
  239.   if (debug)
  240.     printf("read: dev=%x u.u_count=%d\n", dev,
  241.            u.u_count);
  242.  
  243.   /* wait till it's ok to enter */
  244.  
  245.   while (busy)
  246.     sleep((caddr_t) &busy, PRI);
  247.   busy = YES;
  248.  
  249.   /* first get bytes from input q */
  250.  
  251.   while (u.u_count) {
  252.     byte = getc(&in_q);
  253.     if (byte == -1)
  254.       break;    /* used up input q */
  255.     if (passc(byte) == -1) {
  256.       busy = NO;
  257.       wakeup((caddr_t) &busy);
  258.       return;     /* satisfied request */
  259.     }
  260.   }
  261.  
  262.   /* now get straight from device */
  263.  
  264.   while (u.u_count) {
  265.     oldpri = SPLINT();
  266.     while (!DA())
  267.       if (sleep((caddr_t) mpuread, PRI|PCATCH) != 0) {
  268.         splx(oldpri);
  269.         u.u_error = EINTR;
  270.         if (debug)
  271.           printf("read: caught software interrupt\n");
  272.         busy = NO;
  273.         wakeup((caddr_t) &busy);
  274.         return;
  275.       }
  276.       splx(oldpri);
  277.       if (passc(INB(DATA)) == -1)
  278.         break;      /* satisfied request */
  279.   }
  280.  
  281.   busy = NO;
  282.   wakeup((caddr_t) &busy);
  283. }
  284.  
  285. /*-----------------------------------------------------
  286.  * mpuwrite - write data to mpu
  287.  */
  288.  
  289. void mpuwrite(dev)
  290. int dev;
  291. {
  292.   int ret;
  293.  
  294.   if (debug)
  295.     printf("write: dev=%x u.u_count=%d\n", dev,
  296.            u.u_count);
  297.  
  298.   /* wait till it's ok to enter */
  299.  
  300.   while (busy)
  301.     sleep((caddr_t) &busy, PRI);
  302.   busy = YES;
  303.  
  304.   while (u.u_count) {
  305.     ret = waitRR();
  306.     if (ret == E_TIMEOUT) {
  307.       if (debug)
  308.         printf("write: waitRR timed out\n");
  309.       u.u_error = EIO;
  310.       break;
  311.     } else if (ret == E_INTR) {
  312.       if (debug)
  313.         printf("write: waitRR caught software int\n");
  314.       u.u_error = EINTR;
  315.       break;
  316.     } else
  317.       OUTB(DATA, cpass());
  318.   }
  319.  
  320.   busy = NO;
  321.   wakeup((caddr_t) &busy);
  322. }
  323.  
  324. /*-----------------------------------------------------
  325.  * mpuioctl
  326.  */
  327.  
  328. void mpuioctl(dev, cmd, arg, mode)
  329. int dev, cmd;
  330. faddr_t arg;
  331. int mode;
  332. {
  333.   struct mpustuff m;
  334.   int byte, ret, got_intr = NO, oldpri, timeouts;
  335.  
  336.   if (debug)
  337.     printf("ioctl: dev=%x cmd=%x mode=%x ", dev, cmd,
  338.            mode);
  339.  
  340.   /* convert ptr on 286 callers */
  341.  
  342.   if (!IS386())
  343.     arg = (faddr_t) cvttoaddr(arg);
  344.  
  345.   /* make local copy of mpustuff in m */
  346.  
  347.   if (copyin(arg, (char *) &m, sizeof(struct mpustuff))
  348.       == -1) {
  349.     u.u_error = EFAULT;
  350.     if (debug)
  351.       printf("\nioctl: copyin error EFAULT\n");
  352.     return;
  353.   }
  354.   if (!IS386()) {
  355.     m.opbuf = (char *) cvttoaddr(m.opbuf);
  356.     m.resbuf = (char *) cvttoaddr(m.resbuf);
  357.   }
  358.  
  359.   if (debug)
  360.     print